//
//  DownloadManager.swift
//  DownloadTube
//
//  Created by Carlos on 27/10/14.
//  Copyright (c) 2014 Noname. All rights reserved.
//

import UIKit

class DownloadManager: NSObject, NSURLSessionDownloadDelegate {
    
    private let queue:NSOperationQueue = NSOperationQueue()
    var downloads:[BackgroundDownloadTask] = []
    private var sessionConfiguration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.mycompany.downloadtube")
    private var session:NSURLSession?
    private let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
   
    class var sharedInstance: DownloadManager {
        struct Static {
            static var instance: DownloadManager?
            static var token: dispatch_once_t = 0
        }
        
        dispatch_once(&Static.token) {
            Static.instance = DownloadManager()
        }
        
        return Static.instance!
    }
    
    override init() {
        
        super.init()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "clearDownload:", name:"ClearDownload", object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "restartDownload:", name:"RestartDownload", object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "settingsChanged:", name:"kAppSettingChanged", object: nil)
        
        session = NSURLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
    }
    
    func settingsChanged(notification: NSNotification){
        
        let optionChanged = notification.object! as String        
        let valueOptionChanged = NSUserDefaults.standardUserDefaults().objectForKey(optionChanged)! as Int
        
        switch (optionChanged) {
            
            case Settings.options.MobileData.description: sessionConfiguration.allowsCellularAccess = valueOptionChanged == 0 ? false : true
            case Settings.options.SimultaneosDownloads.description: sessionConfiguration.HTTPMaximumConnectionsPerHost = valueOptionChanged
            default: break;
        }
   }
    
    func addVideoStreamToDownload(video:Video, videoStream:VideoStream){
        
        let backgroundDownloadTask = BackgroundDownloadTask(video: video, videoStream: videoStream)
        let downloadTask = session?.downloadTaskWithURL(videoStream.videoURL)
        downloadTask?.resume()
        backgroundDownloadTask.downloadTask = downloadTask
        downloads.append(backgroundDownloadTask)
        NSNotificationCenter.defaultCenter().postNotificationName("NewDownload", object: backgroundDownloadTask)
    }
    
    func listDownloads() -> [BackgroundDownloadTask]{
        
        return downloads
    }
    
    func clearDownload(notification:NSNotification){
        
        let downloadTaskToClear = notification.object as BackgroundDownloadTask
        let index = (downloads as NSArray).indexOfObject(downloadTaskToClear)
        downloads.removeAtIndex(index)
    }
    
    func restartDownload(notification:NSNotification){
        
        let downloadTaskToRestart = notification.object! as DownloadTask
        let index = (downloads as NSArray).indexOfObject(downloadTaskToRestart)
        
        downloadTaskToRestart.clearTask()
        addVideoStreamToDownload(downloadTaskToRestart.video!, videoStream: downloadTaskToRestart.videoStream!)
    }
    
    /* Sent periodically to notify the delegate of download progress. */
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64){
        
         Async.background {
            
            if let index = self.getBackgroundDownloadTaskIndex(downloadTask) {

                self.downloads[index].numOfReadBytes = totalBytesWritten
                self.downloads[index].numOfExpectedBytes = totalBytesExpectedToWrite
               NSNotificationCenter.defaultCenter().postNotificationName("UpdateDownload", object: index)
            }
        }
    }
    
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL){
        
        if let index = self.getBackgroundDownloadTaskIndex(downloadTask) {
     
            let videoId = NSUUID().UUIDString.stringByReplacingOccurrencesOfString("-", withString: "", options: .LiteralSearch, range: nil)
            let backTask = downloads[index]
            
            let imageToSaveFilename = documentsPath.stringByAppendingPathComponent(videoId+"."+backTask.video.thumbnail.lastPathComponent!.pathExtension)
            NSData(contentsOfURL: backTask.video.thumbnail)!.writeToFile(imageToSaveFilename, atomically: true)
            
            let videoToSaveFilename = documentsPath.stringByAppendingPathComponent("\(videoId).mp4")
            NSFileManager.defaultManager().copyItemAtURL(location, toURL: NSURL(fileURLWithPath: videoToSaveFilename)!, error: nil)
           
            backTask.videoFilename = videoToSaveFilename.lastPathComponent
            
            let error = VideoDao.sharedInstance.saveVideo(backTask.video.id,  title: backTask.video.title, author: backTask.video.author, filename: videoToSaveFilename.lastPathComponent, thumbnailFilename: imageToSaveFilename.lastPathComponent, type: "\(backTask.videoStream.streamId)", downloadDate: NSDate(), spaceOnDisk: backTask.numOfExpectedBytes, length: backTask.video.length)
        
            self.downloads[index].numOfReadBytes = downloadTask.countOfBytesReceived
            self.downloads[index].numOfExpectedBytes = downloadTask.countOfBytesExpectedToReceive
            
            NSNotificationCenter.defaultCenter().postNotificationName("FinishedDownload", object: index)
            endDownloadLocalNotification(backTask)
        }
        
        println("end!!")
    }
    
    func clearDownloadTask(index:Int){

        let taskToClear = downloads[index]
        
        if (!taskToClear.isCompleted()) {
            
            taskToClear.cancelDownload()
        }
        
        downloads.removeAtIndex(index)
    }
    
    func clearDownloadTask(downloadTask:BackgroundDownloadTask){
        
        let index = (downloads as NSArray).indexOfObject(downloadTask)
        clearDownloadTask(index)
    }
    
    func getBackgroundDownloadTaskIndex(downloadTask:NSURLSessionDownloadTask) -> Int? {
       
        for (index, value) in enumerate(downloads) {
            
            if (value.downloadTask == downloadTask) {
                
                return index
            }
        }
        return nil
    }
    
    func endDownloadLocalNotification(downloadTask: BackgroundDownloadTask){
        
        let localNotification = UILocalNotification()
        localNotification.fireDate = NSDate()
        localNotification.alertBody = Utils.localizedString("%@ has been downloaded successfully!", arguments: [downloadTask.video.title])
        localNotification.alertAction = Utils.localizedString("play this video")
        localNotification.applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + 1
        
        UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
        
    }
    
    
}
